{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f6aa1a0d",
   "metadata": {},
   "source": [
    "## Lesson 1: Simple string modification"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "71224cfe",
   "metadata": {},
   "source": [
    "**Objectives**: manipulate the data of a resource; run a modifier; flush a modified resource to disk"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "fae6f8ac",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using OFRAK Community License.\n"
     ]
    }
   ],
   "source": [
    "from ofrak import OFRAK\n",
    "from ofrak_tutorial.helper_functions import create_hello_world_binary\n",
    "\n",
    "create_hello_world_binary()\n",
    "\n",
    "ofrak = OFRAK()\n",
    "basic_context = await ofrak.create_ofrak_context()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "05d10bd0",
   "metadata": {},
   "source": [
    "We create an async function taking an OFRAK context as its first argument:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "b97591b8",
   "metadata": {},
   "outputs": [],
   "source": [
    "from ofrak.core import BinaryPatchModifier, BinaryPatchConfig\n",
    "\n",
    "\n",
    "async def replace_hello_world(ofrak_context, input_filename, output_filename):\n",
    "    # Create the root resource from the input file\n",
    "    root_resource = await ofrak_context.create_root_resource_from_file(input_filename)\n",
    "\n",
    "    # Get the raw bytes from the resource\n",
    "    data = await root_resource.get_data()\n",
    "\n",
    "    # Find the \"Hello, World!\" string in the data\n",
    "    hello_world_offset = data.find(b\"Hello, World!\")\n",
    "\n",
    "    # Patch the binary by writing the null-terminated string \"Meow!\" over\n",
    "    # the first occurrence of \"Hello, World!\" using the BinaryPatchModifier\n",
    "    await root_resource.run(BinaryPatchModifier, BinaryPatchConfig(hello_world_offset, b\"Meow!\\0\"))\n",
    "\n",
    "    # Flush the modified program to disk\n",
    "    await root_resource.flush_data_to_disk(output_filename)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dd70d617",
   "metadata": {},
   "source": [
    "This illustrates the way we run modifiers: using `resource.run(<modifier>, <modifier config>)`."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9bab75c6",
   "metadata": {},
   "source": [
    "Let's see if it works:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "d8070158",
   "metadata": {},
   "outputs": [],
   "source": [
    "await replace_hello_world(basic_context, \"hello_world\", \"meow_world\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "9be0423e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Meow!\n"
     ]
    }
   ],
   "source": [
    "%%bash\n",
    "\n",
    "chmod +x meow_world && ./meow_world"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d5d09317",
   "metadata": {},
   "source": [
    "[Next page](2_ofrak_internals.ipynb)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.18"
  },
  "pycharm": {
   "stem_cell": {
    "cell_type": "raw",
    "metadata": {
     "collapsed": false
    },
    "source": []
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
